diff options
Diffstat (limited to 'app/api/data-room/[projectId]/upload')
| -rw-r--r-- | app/api/data-room/[projectId]/upload/route.ts | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/app/api/data-room/[projectId]/upload/route.ts b/app/api/data-room/[projectId]/upload/route.ts new file mode 100644 index 00000000..60bbc10f --- /dev/null +++ b/app/api/data-room/[projectId]/upload/route.ts @@ -0,0 +1,139 @@ +// app/api/data-room/[projectId]/upload/route.ts +import { NextRequest, NextResponse } from 'next/server'; +import { getServerSession } from 'next-auth/next'; +import { authOptions } from '@/app/api/auth/[...nextauth]/route'; +import { FileService, type FileAccessContext } from '@/lib/services/fileService'; +import { saveDRMFile, saveFileStream } from '@/lib/file-stroage'; + +export async function POST( + request: NextRequest, + { params }: { params: { projectId: string } } +) { + try { + const session = await getServerSession(authOptions); + if (!session?.user) { + return NextResponse.json({ error: '인증이 필요합니다' }, { status: 401 }); + } + + const context: FileAccessContext = { + userId: Number(session.user.id), + userDomain: session.user.domain || 'partners', + userEmail: session.user.email, + ipAddress: request.ip || request.headers.get('x-forwarded-for') || undefined, + userAgent: request.headers.get('user-agent') || undefined, + }; + + // 내부 사용자만 업로드 가능 + if (session.user.domain === 'partners') { + return NextResponse.json( + { error: '파일 업로드 권한이 없습니다' }, + { status: 403 } + ); + } + + const formData = await request.formData(); + const file = formData.get('file') as File; + const category = formData.get('category') as string; + const parentId = formData.get('parentId') as string | null; + const fileSize = formData.get('fileSize') as string | null; + + if (!file) { + return NextResponse.json( + { error: '파일이 제공되지 않았습니다' }, + { status: 400 } + ); + } + + // 대용량 파일 임계값 (10MB) + const LARGE_FILE_THRESHOLD = 10 * 1024 * 1024; + const actualFileSize = fileSize ? parseInt(fileSize) : file.size; + + let result; + + // 파일 크기에 따라 다른 저장 방법 사용 + if (actualFileSize > LARGE_FILE_THRESHOLD) { + console.log(`🚀 대용량 파일 스트리밍 저장: ${file.name} (${(actualFileSize / 1024 / 1024).toFixed(2)}MB)`); + + // 대용량 파일은 스트리밍 저장 사용 + result = await saveFileStream({ + file, + directory: `projects/${params.projectId}`, + originalName: file.name, + userId: session.user.id + }); + } else { + console.log(`📦 일반 파일 저장: ${file.name} (${(actualFileSize / 1024 / 1024).toFixed(2)}MB)`); + + // 작은 파일은 기존 DRM 저장 방식 사용 + result = await saveDRMFile( + file, + async (file) => file.arrayBuffer(), // 이미 복호화된 데이터 + `projects/${params.projectId}`, + session.user.id + ); + } + + if (!result.success) { + return NextResponse.json( + { error: result.error || '파일 저장에 실패했습니다' }, + { status: 500 } + ); + } + + // DB에 파일 정보 저장 + const fileService = new FileService(); + const newFile = await fileService.createFileItem( + { + name: result.originalName || file.name, + type: 'file', + category: category as 'public' | 'restricted' | 'confidential' | 'internal', + parentId, + size: result.fileSize || actualFileSize, + mimeType: file.type, + filePath: result.publicPath, + projectId: params.projectId, + }, + context + ); + + return NextResponse.json({ + ...newFile, + uploadResult: { + ...result, + uploadMethod: actualFileSize > LARGE_FILE_THRESHOLD ? 'stream' : 'buffer', + fileSizeMB: (actualFileSize / 1024 / 1024).toFixed(2) + }, + }, { status: 201 }); + + } catch (error) { + console.error('파일 업로드 오류:', error); + return NextResponse.json( + { + error: '파일 업로드에 실패했습니다', + details: error instanceof Error ? error.message : undefined + }, + { status: 500 } + ); + } +} + +// 업로드 진행률 확인 (선택적) +export async function GET( + request: NextRequest, + { params }: { params: { projectId: string } } +) { + try { + const session = await getServerSession(authOptions); + if (!session?.user) { + return NextResponse.json({ error: '인증이 필요합니다' }, { status: 401 }); + } + + // 업로드 상태 확인 로직 (필요시 구현) + return NextResponse.json({ message: '업로드 상태 확인 엔드포인트' }); + } catch (error) { + return NextResponse.json( + { error: '상태 확인 실패' }, + { status: 500 } + ); + } +}
\ No newline at end of file |
